package net.zoneland.knowledge.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.page.PageMethod;
import com.google.common.collect.ImmutableList;
import net.zoneland.knowledge.config.TalkConfig;
import net.zoneland.knowledge.controller.bean.SanHuiYiKeVo;
import net.zoneland.knowledge.dao.*;
import net.zoneland.knowledge.enums.SubmitDraftOperatorType;
import net.zoneland.knowledge.exceptions.WorkApplyException;
import net.zoneland.knowledge.model.*;
import net.zoneland.knowledge.service.NotifyService;
import net.zoneland.knowledge.service.WorkApplyInfoService;
import net.zoneland.knowledge.service.WorkReminderService;
import net.zoneland.knowledge.service.bean.MemberVo;
import net.zoneland.knowledge.service.bean.ReceiverNameVo;
import net.zoneland.knowledge.service.bean.ReceiverUidVo;
import net.zoneland.knowledge.service.bean.WorkReminderVo;

import net.zoneland.knowledge.utils.ExcelFillCellMergeStrategyUtils;
import net.zoneland.knowledge.utils.LocalDateTimeConverter;
import net.zoneland.knowledge.utils.OplogUtils;
import net.zoneland.knowledge.utils.TitleSheetWriteHandler;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class WorkReminderServiceImpl implements WorkReminderService {

    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WorkReminderServiceImpl.class);

    @Autowired
    private WorkReminderMapper workReminderMapper;

    @Autowired
    private PartyOrgMapper partyOrgMapper;

    @Autowired
    private PartyUserMapper partyUserMapper;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private WorkApplyInfoService workApplyInfoService;

    @Autowired
    private TalkConfig talkConfig;

    @Autowired
    private SanHuiYiKeMapper sanHuiYiKeMapper;

    /**
     * 党小组织数据接口.
     */
    @Autowired
    private PartyGroupMapper partyGroupMapper;

    /**
     * json工具类.
     */
    @Autowired
    protected ObjectMapper objectMapper;

    /**
     * 市公司
     */
    private static final String PROVINCE = "province";

    /**
     * 市公司
     */
    private static final String CITY = "city";

    /**
     * 支部
     */
    private static final String PARTY_BRANCH = "partyBranch";

    /**
     * 未下发
     */
    private static final String ISSUED_TODO = "未下发";

    /**
     * 已下发
     */
    private static final String ISSUED_DO = "已下发";

    /**
     * 未分派
     */
    private static final String ASSIGN_TODO = "未分派";

    /**
     * 已分派
     */
    private static final String ASSIGN_DO = "已分派";

    /**
     * 已分派
     */
    private static final String NO_RECEIVED = "未接收";

    /**
     * 待处理
     */
    private static final String TODO = "todo";

    /**
     * 接受
     */
    private static final String ACCEPT = "accept";

    /**
     * 任务状态-新增
     */
    private static final String TASK_ADD = "新增";

    /**
     * 任务状态-修改
     */
    private static final String TASK_UPDATE = "修改";

    /**
     * 主工单
     */
    private static final String MAIN_WORK = "mainWork";

    /**
     * 主工单
     */
    private static final String ATTACHMENTS = "attachments";

    /**
     * 已完成
     */
    private static final String COMPLETE = "已完成";

    /**
     * 支部工单完成状态-未完成
     */
    private static final String INCOMPLETE = "未完成";

    /**
     * 任务id值
     */
    private static final String TASK_ID = "undefined";

    /**
     * 接受类型
     */
    private static final String RECEIVER_TYPE = "person";

    /**
     * 321任务发布提醒标题
     */
    private static final String WORK_APPLY_TITLE = "新的321任务发布提醒";

    /**
     * 321任务发布提醒主任务名称
     */
    private static final String MAIN_TASK_NAME = "落实事项：%s\n责任人：%s\n细化说明：%s\n工作子项：%s\n工作特性：%s";

    /**
     * 321任务发布提醒内容
     */
    private static final String WORK_APPLY_CONTENT = "有新的321任务发布了,请登录“红小智” 在 智办-常用工具 中点击“321提醒” 查看";

    /**
     * 组织结构
     */
    private static final String PARTY_GENERAL_BRANCH = "党总支";

    /**
     * 三月
     */
    private static final int MARCH = 3;

    /**
     * 计算八个月前的日期的月份
     */
    private static final int EIGHT_MONTH = 8;

    /**
     * 任务类型-必做
     */
    private static final String MUST_DO = "必做";

    /**
     * 任务类型-选做
     */
    private static final String OPTIONAL = "选做";

    /**
     * 逗号
     */
    private static final String COMMA = ",";

    /**
     * 党支部工作321提醒
     */
    private static final String SHEET_NAME = "党支部工作321提醒";

    /**
     * 设置省公司导出第几列开始合并
     */
    private static final int[] PROVINCE_MERGE_COLUMN_INDEX = {0, 1, 2, 3, 4, 5, 6};

    /**
     * 省公司导出标题合并列数
     */
    private static final int PROVINCE_MERGE_COL = 12;

    /**
     * 设置市公司导出第几列开始合并
     */
    private static final int[] CITY_MERGE_COLUMN_INDEX = {0, 1, 2, 3, 4, 5, 6, 7};

    /**
     * 市公司导出标题合并列数
     */
    private static final int CITY_MERGE_COL = 13;

    /**
     * 设置支部导出第几列开始合并
     */
    private static final int[] BRANCH_MERGE_COLUMN_INDEX = {0, 1, 2, 3, 4, 5, 6};

    /**
     * 支部导出标题合并列数
     */
    private static final int BRANCH_MERGE_COL = 12;

    /**
     * 设置第几行开始合并
     */
    private static final int MERGE_ROW_INDEX = 1;

    @Override
    public List<TaskReminderMainWork> getProvinceWorkList(final WorkReminderVo vo) {
        // 查询省公司主任务工单列表
        if (vo.getPage() != null && vo.getPageSize() != null) {
            PageMethod.startPage(vo.getPage(), vo.getPageSize());
        }

        final List<TaskReminderMainWork> mainWorks = workReminderMapper.getProvinceMainWorkList(vo);
        return mainWorks.stream().map(mainWork ->
                setMainWorkDescriptions(mainWork, workReminderMapper.getProvinceSubWorkList(mainWork))).collect(Collectors.toList());
    }

    @Override
    public List<TaskReminderSubWork> getProvinceSubWorkList(final String mainWorkId) {
        final TaskReminderMainWork mainWork = new TaskReminderMainWork();
        mainWork.setWorkOrderId(mainWorkId);
        return workReminderMapper.getProvinceSubWorkList(mainWork);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskReminderMainWork saveOrUpdateProvinceWork (final TaskReminderMainWork mainWork, final LoginUserPojo loginUserPojo) {

        mainWork.setTaskStatus(StringUtils.equals(mainWork.getWorkStatus(), ISSUED_DO) ? TASK_UPDATE : mainWork.getTaskStatus());

        mainWork.setWorkStatus(ISSUED_TODO);
        if (StringUtils.isNotBlank(mainWork.getId())) {
            mainWork.setUpdateTime(LocalDateTime.now());
            workReminderMapper.updateProvinceMainWork(mainWork);
            return mainWork;
        }
        // 插入省公司主表数据
        final String workOrderId = UUID.randomUUID().toString();
        mainWork.setId(workOrderId);
        mainWork.setWorkOrderId(workOrderId);
        mainWork.setCreateTime(LocalDateTime.now());
        mainWork.setTaskStatus(TASK_ADD);
        workReminderMapper.insertProvinceMainWork(mainWork);

        // 插入子公司工单
        ListUtils.emptyIfNull(mainWork.getTaskReminderSubWorks()).stream()
                .peek(subWork -> setSubTask(subWork, workOrderId))
                .forEach(workReminderMapper::insertProvinceSubWork);

        return mainWork;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateProvinceSubWork(final TaskReminderSubWork subWork) {

        // 修改主工单状态
        final TaskReminderMainWork mainWork = workReminderMapper.getProvinceMainWorkByMainWorkId(subWork.getMainWorkId());
        mainWork.setTaskStatus(StringUtils.equals(mainWork.getWorkStatus(), ISSUED_DO) ? TASK_UPDATE : mainWork.getTaskStatus());
        mainWork.setWorkStatus(ISSUED_TODO);
        mainWork.setUpdateTime(LocalDateTime.now());
        workReminderMapper.updateProvinceMainWork(mainWork);

        if (StringUtils.isNotBlank(subWork.getId())) {
            workReminderMapper.updateProvinceSubWork(subWork);
            return;
        }

        setSubTask(subWork, null);
        subWork.setCreateTime(LocalDateTime.now());

        workReminderMapper.insertProvinceSubWork(subWork);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProvinceMainWork(final TaskReminderMainWork mainWork) {
        workReminderMapper.deleteProvinceMainWork(mainWork);

        final List<String> subWorkIds = workReminderMapper.getProvinceSubWorkList(mainWork)
                .stream()
                .map(TaskReminderSubWork::getSubWorkId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(subWorkIds)) {
            workReminderMapper.deleteProvinceSubWork(subWorkIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProvinceSubWork(final TaskReminderSubWork subWork) {
        workReminderMapper.deleteProvinceSubWork(ImmutableList.of(subWork.getSubWorkId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void issuedWork(final List<TaskReminderMainWork> mainWorks, final LoginUserPojo user, final HttpServletRequest request) {
        // 暂时禁用创建流程功能
        final String companyName = request.getParameter("companyName");
        // 获取下发人员列表信息
        final List<IssuedMember> issuedMembers = workReminderMapper.getIssuedMemberByCompanyName(companyName);

        // 获取日期最大的主任务信息
        final Comparator<TaskReminderMainWork> comparator = Comparator.comparing(TaskReminderMainWork::getFinishTime);
        final TaskReminderMainWork taskReminderMainWork = Collections.max(mainWorks, comparator);

        // 创建任务流程工单
        createWorkApply(user, request, issuedMembers, companyName, taskReminderMainWork);

        final LocalDateTime nowDate = LocalDateTime.now();
        final List<PartyOrg> partyOrgs = partyOrgMapper.getOrgTree();
        mainWorks.forEach(mainWork -> {
            mainWork.setIssuedTime(nowDate);

            switch (mainWork.getIssuedType()) {
                case CITY:
                    // 省公司下发
                    processCityMainWork(mainWork, partyOrgs);
                    break;
                case PARTY_BRANCH:
                    // 市公司下发
                    processPartyBranchMainWork(mainWork, partyOrgs);
                    break;
                default:
                    break;
            }
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void acceptWork(final TaskReminderMainWork mainWork) {
        // 工单下发状态设为未下发、已接受
        mainWork.setWorkStatus(ASSIGN_TODO);
        mainWork.setReadType(ACCEPT);

        // 接受过的市公司任务信息
        final TaskReminderMainWork oldMainWork = workReminderMapper.getCityMainWorkByIdAndParentWorkId(mainWork);

        // 如果市公司任务信息为空，则修改市公司下发的工单信息状态为已下发，否则直接更新任务信息到已接受的任务上
        if (Objects.isNull(oldMainWork)) {
            workReminderMapper.updateCityMainWork(mainWork);
            return;
        }

        // 清除待接受的市公司任务信息
        workReminderMapper.deleteCityMainWorkById(ImmutableList.of(mainWork.getId()));
        workReminderMapper.deleteCitySubWorkById(ImmutableList.of(oldMainWork.getWorkOrderId()));

        // 更新子工单信息
        workReminderMapper.updateCitySubWorkByMainWorkId(mainWork.getWorkOrderId(), oldMainWork.getWorkOrderId());

        // 将旧数据更新为接受的新数据
        mainWork.setWorkOrderId(oldMainWork.getWorkOrderId());
        workReminderMapper.updateCityMainWork(mainWork);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskReminderMainWork saveOrUpdateCityMainWork(final TaskReminderMainWork mainWork, final LoginUserPojo loginUserPojo) {

        mainWork.setWorkStatus(ASSIGN_TODO);
        if (StringUtils.isBlank(mainWork.getId())) {

            final String workOrderId = UUID.randomUUID().toString();
            mainWork.setId(workOrderId);
            mainWork.setWorkOrderId(workOrderId);
            mainWork.setUserId(loginUserPojo.getUserID());
            mainWork.setUserName(loginUserPojo.getUserName());
            mainWork.setCreateTime(LocalDateTime.now());
            mainWork.setReadType(ACCEPT);
            mainWork.setTaskStatus(TASK_ADD);

            workReminderMapper.insertCityMainWork(mainWork);

            insertCitySubWork(mainWork, workOrderId);
        } else {
            final String taskStatus = StringUtils.isNotBlank(mainWork.getTaskStatus()) && StringUtils.equals(mainWork.getWorkStatus(), ISSUED_DO)
                    ? TASK_UPDATE : mainWork.getTaskStatus();
            mainWork.setTaskStatus(taskStatus);
            mainWork.setUpdateTime(LocalDateTime.now());
            workReminderMapper.updateCityMainWork(mainWork);
        }
        return mainWork;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCitySubWork(final TaskReminderSubWork subWork) {

        // 修改主工单状态
        final TaskReminderMainWork mainWork = workReminderMapper.getCityMainWorkByMainWorkId(subWork.getMainWorkId());
        mainWork.setTaskStatus(StringUtils.equals(mainWork.getWorkStatus(), ISSUED_DO) ? TASK_UPDATE : mainWork.getTaskStatus());
        mainWork.setWorkStatus(ISSUED_TODO);
        mainWork.setUpdateTime(LocalDateTime.now());
        workReminderMapper.updateProvinceMainWork(mainWork);

        if (StringUtils.isNotBlank(subWork.getId())) {
            workReminderMapper.updateCitySubWork(subWork);
            return;
        }

        setSubTask(subWork, null);
        workReminderMapper.insertCitySubWork(subWork);
    }

    @Override
    public void deleteCityMainWork(final TaskReminderMainWork mainWork) {
        workReminderMapper.deleteCityMainWorkById(ImmutableList.of(mainWork.getId()));

        final List<String> subWorkIds = workReminderMapper.getCitySubWorkList(mainWork)
                .stream()
                .map(TaskReminderSubWork::getSubWorkId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(subWorkIds)) {
            workReminderMapper.deleteCitySubWork(subWorkIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCitySubWork(final TaskReminderSubWork subWork) {
        workReminderMapper.deleteCitySubWork(ImmutableList.of(subWork.getSubWorkId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCitySubWork(final TaskReminderSubWork subWork) {
        setSubTask(subWork, null);
        workReminderMapper.insertCitySubWork(subWork);
    }

    @Override
    public List<TaskReminderMainWork> getCityWorkList(final WorkReminderVo vo) {
        // 查询省公司主任务工单列表
        if (vo.getPage() != null && vo.getPageSize() != null) {
            PageMethod.startPage(vo.getPage(), vo.getPageSize());
        }
        final List<TaskReminderMainWork> taskReminderMainWorks = workReminderMapper.getCityMainWorkList(vo);
        final Stream<TaskReminderMainWork> cityMainWorkStream = taskReminderMainWorks.stream()
                .peek(mainWork -> {
                    if (StringUtils.equals(mainWork.getWorkStatus(), ASSIGN_DO)) {
                        mainWork.setMainWorkTotal(workReminderMapper.getBranchMainWorkCountByParentWorkId(mainWork.getCompanyName(), mainWork.getWorkOrderId()));
                        mainWork.setFinishMainWorkCount(workReminderMapper.getBranchCountByParentWorkIdAndFinishStatus(mainWork.getCompanyName(), mainWork.getWorkOrderId()));
                    }
                }).map(mainWork -> setMainWorkDescriptions(mainWork, workReminderMapper.getCitySubWorkList(mainWork)));

        // 工单完成状态筛选
        return getMainWorkByFinishStatus(cityMainWorkStream, vo.getFinishStatus());
    }

    @Override
    public List<TaskReminderSubWork> getCitySubWorkList(final String mainWorkId) {
        final TaskReminderMainWork mainWork = new TaskReminderMainWork();
        mainWork.setWorkOrderId(mainWorkId);
        return workReminderMapper.getCitySubWorkList(mainWork);
    }

    @Override
    public List<TaskReminderMainWork> getBranchWorkList(final WorkReminderVo vo) {
        // 查询省公司主任务工单列表
        if (vo.getPage() != null && vo.getPageSize() != null) {
            PageMethod.startPage(vo.getPage(), vo.getPageSize());
        }
        final List<TaskReminderMainWork> mainWorks = workReminderMapper.getBranchMainWorkList(vo);
        return mainWorks.stream().map(mainWork ->
                setMainWorkDescriptions(mainWork, workReminderMapper.getBranchSubWorkList(mainWork))).collect(Collectors.toList());
    }

    @Override
    public List<TaskReminderSubWork> getBranchSubWorkList(final String mainWorkId) {
        final TaskReminderMainWork mainWork = new TaskReminderMainWork();
        mainWork.setWorkOrderId(mainWorkId);
        return workReminderMapper.getBranchSubWorkList(mainWork);
    }

    @Override
    public List<PartyOrg> getOrgTree() {
        return partyOrgMapper.getOrgTree();
    }

    @Override
    public List<PartyUser> getCityPartyUser() {
        return partyUserMapper.getCityPartyUser();
    }

    @Override
    public List<PartyUser> getGanshiByCompany(final String companyName) {
        return partyUserMapper.getGanshiByCompany(companyName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDefaultMembers(final List<MemberVo> userList, final String issuedType, final String companyName) {
        // 清除对应公司的默认人员信息
        workReminderMapper.deleteDefaultMembers(companyName);

        // 插入新的人员名单
        CollectionUtils.emptyIfNull(userList).stream().map(user -> {
            final IssuedMember issuedMember = new IssuedMember();
            issuedMember.setId(UUID.randomUUID().toString());
            issuedMember.setIssuedType(issuedType);
            issuedMember.setUserId(user.getId());
            issuedMember.setUserName(user.getName());
            issuedMember.setOrgShortName(user.getOrgShortName());
            issuedMember.setUserType(user.getUserType());
            issuedMember.setCompanyName(companyName);
            return issuedMember;
        }).forEach(issuedMember -> workReminderMapper.saveDefaultMembers(issuedMember));
    }

    @Override
    public List<IssuedMember> getDefaultMembers(final String companyName) {
        return workReminderMapper.getIssuedMemberByCompanyName(companyName);
    }

    @Override
    public List<SanHuiYiKe> autoSearchMeetingList(final SanHuiYiKeVo sanHuiYiKeVo) {
        // 获取党小组uuid
        final List<String> orgGroupUuids = partyGroupMapper.getOrgGroupUuidByParentIds(sanHuiYiKeVo.getOrgUuids());
        sanHuiYiKeVo.setOrgUuids(ListUtils.union(sanHuiYiKeVo.getOrgUuids(), orgGroupUuids));

        return sanHuiYiKeMapper.searchByOrgUuidAndMeetingNames(sanHuiYiKeVo, getSearchMeetingDate());
    }

    @Override
    public List<SanHuiYiKe> searchMeetingList(final SanHuiYiKeVo sanHuiYiKeVo) {
        // 获取党小组uuid
        final List<String> orgGroupUuids = partyGroupMapper.getOrgGroupUuidByParentIds(sanHuiYiKeVo.getOrgUuids());
        sanHuiYiKeVo.setOrgUuids(ListUtils.union(sanHuiYiKeVo.getOrgUuids(), orgGroupUuids));

        return sanHuiYiKeMapper.searchByOrgUuid(sanHuiYiKeVo, getSearchMeetingDate());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finishWork(final HttpServletRequest request, final LoginUserPojo user ) throws JsonProcessingException {

        final TaskReminderMainWork mainWork = objectMapper.readValue(request.getParameter(MAIN_WORK), TaskReminderMainWork.class);
        workReminderMapper.updateBranchMainWork(mainWork);

        saveFile(request, mainWork, user);

    }

    @Override
    public List<SanHuiYiKe> searchMeetingByMainWork(final TaskReminderMainWork mainWork) {
        if (StringUtils.isBlank(mainWork.getMeetingIds())) {
            return Collections.emptyList();
        }
        final String[] ids = mainWork.getMeetingIds().split(",");
        return sanHuiYiKeMapper.searchByIds(ids);
    }

    @Override
    public List<BranchAttachment> getBranchAttachmentByMainWork(final String mainWorkOrderId) {
        return workReminderMapper.getBranchAttachmentByMainWorkId(mainWorkOrderId);
    }

    @Override
    public BranchAttachment getBranchAttachmentById(final String id) {
        return workReminderMapper.getBranchAttachmentById(id);
    }

    @Override
    public List<TaskReminderMainWork> getBranchMainWorkByParentWorkId(final TaskReminderMainWork mainWork) {
        return workReminderMapper.getBranchMainWorkByParentWorkId(mainWork);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveFile(final HttpServletRequest request, final TaskReminderMainWork mainWork, final LoginUserPojo user) {
        final MultipartHttpServletRequest multipartReq = (MultipartHttpServletRequest) request;
        final List<MultipartFile> fileRes = multipartReq.getFiles(ATTACHMENTS);
        final LocalDateTime nowDate = LocalDateTime.now();
        fileRes.stream()
                .filter(Objects::nonNull)
                .forEach(file -> {
                    try {
                        final BranchAttachment branchAttachment = new BranchAttachment()
                                .setAttachment(file.getBytes())
                                .setId(UUID.randomUUID().toString())
                                .setMainWorkId(mainWork.getWorkOrderId())
                                .setFileName(file.getOriginalFilename())
                                .setUploaderTime(nowDate)
                                .setUploaderUid(user.getUserID())
                                .setUploaderName(user.getUserName());
                        workReminderMapper.insertBranchAttachment(branchAttachment);
                    } catch (final IOException e) {
                        LOGGER.error("获取文件流失败，文件名称:{}", file.getOriginalFilename(), e);
                        throw new WorkApplyException("保存文件失败，文件名称:" + file.getOriginalFilename(), e);
                    }
                });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBranchAttachmentById(final String fileId) {
        workReminderMapper.deleteBranchAttachmentById(fileId);
    }

    @Override
    public TaskReminderMainWork getCityMainWorkByMainWorkId(final String parentMainId) {
        return workReminderMapper.getCityMainWorkByMainWorkId(parentMainId);
    }

    @Override
    public List<PartyOrg> getBranchByOrgUuid(final String orgUuid) {
        final List<PartyOrg> orgList = new ArrayList<>();
        final PartyOrg partyOrg = partyOrgMapper.getOrgByUuid(orgUuid);
        orgList.add(partyOrg);
        // 获取父组织结构
        final PartyOrg parentPartyOrg = partyOrgMapper.getOrgByUuid(partyOrg.getParentOrgUuid());
        if (StringUtils.equals(parentPartyOrg.getOrgType(), PARTY_GENERAL_BRANCH)) {
            orgList.add(parentPartyOrg);
        }
        return orgList;
    }

    @Override
    public void remindersContentExport(final WorkReminderVo workReminderVo, final HttpServletResponse response) {

        switch (workReminderVo.getExportType()) {
            case PROVINCE:
                provinceExport(workReminderVo, response);
                break;
            case CITY:
                cityExport(workReminderVo, response);
                break;
            case PARTY_BRANCH:
                branchExport(workReminderVo, response);
                break;
        }

    }

    /**
     * 更新省公司工单状态
     * @param mainWork 主工单信息
     * @param partyOrgs 党组织结构
     */
    private void processCityMainWork(final TaskReminderMainWork mainWork, final List<PartyOrg> partyOrgs) {
        // 更新省公司工单状态
        mainWork.setWorkStatus(ISSUED_DO);
        workReminderMapper.updateProvinceMainWork(mainWork);

        deleteOldCityMainWorks(mainWork);

        final List<String> companyNames = partyOrgs.stream()
                .map(PartyOrg::getCompanyName)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());

        createNewCityMainWork(mainWork, companyNames);
    }

    /**
     * 创建新的市公司工单
     * @param mainWork 工单信息
     * @param companyNames 公司列表
     */
    private void createNewCityMainWork(final TaskReminderMainWork mainWork, final List<String> companyNames) {
        final LocalDateTime nowDate = LocalDateTime.now();
        mainWork.setParentWorkId(mainWork.getWorkOrderId());
        mainWork.setReadType(TODO);
        mainWork.setCreateTime(nowDate);
        mainWork.setUpdateTime(nowDate);
        final List<TaskReminderSubWork> provinceSubWorks = workReminderMapper.getProvinceSubWorkList(mainWork);
        companyNames.forEach(companyName -> {
            final String mainWorkId = UUID.randomUUID().toString();
            mainWork.setId(mainWorkId);
            mainWork.setWorkOrderId(mainWorkId);
            mainWork.setCompanyName(companyName);

            workReminderMapper.insertCityMainWork(mainWork);

            provinceSubWorks.forEach(subWork -> {
                setSubTask(subWork, mainWorkId);
                workReminderMapper.insertCitySubWork(subWork);
            });

        });

    }

    /**
     * 更新旧的支部工单信息
     * @param mainWork 工单信息
     * @param oldMainWorks 支部旧工单信息列表
     */
    private void updateOldBranchMainWork(final TaskReminderMainWork mainWork, final List<TaskReminderMainWork> oldMainWorks) {
        ListUtils.emptyIfNull(oldMainWorks).forEach(oldMainWork -> {
            // 更新支部任务信息
            oldMainWork.setMatterDescription(mainWork.getMatterDescription());
            oldMainWork.setUserName(mainWork.getUserName());
            oldMainWork.setSanKeKeywords(mainWork.getSanKeKeywords());
            oldMainWork.setFinishTime(mainWork.getFinishTime());
            oldMainWork.setWorkType(mainWork.getWorkType());

            workReminderMapper.updateBranchMainWork(oldMainWork);
        });

        final List<String> workOrderIds = oldMainWorks.stream()
                .map(TaskReminderMainWork::getWorkOrderId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());
        // 清除旧的子任务信息
        if (CollectionUtils.isNotEmpty(workOrderIds)) {
            workReminderMapper.deleteBranchSubWorkById(workOrderIds);
        }

        final List<TaskReminderSubWork> citySubWorks = workReminderMapper.getCitySubWorkList(mainWork);
        // 插入新的子任务信息
        if (CollectionUtils.isNotEmpty(citySubWorks)) {
            ListUtils.emptyIfNull(oldMainWorks).forEach(oldMainWork -> citySubWorks.stream()
                    .peek(subWork -> setSubTask(subWork, oldMainWork.getWorkOrderId()))
                    .forEach(workReminderMapper::insertBranchSubWork));
        }

    }

    /**
     * 删除旧的市公司工单信息
     * @param mainWork 工单信息
     */
    private void deleteOldCityMainWorks(final TaskReminderMainWork mainWork) {
        final List<TaskReminderMainWork> oldMainWorks = workReminderMapper.getCityMainWorkByParentWorkId(mainWork);
        final List<String> workIds = oldMainWorks.stream().map(TaskReminderMainWork::getId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        final List<String> workOrderIds = oldMainWorks.stream()
                .map(TaskReminderMainWork::getWorkOrderId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(workIds)) {
            workReminderMapper.deleteCityMainWorkById(workIds);
        }

        if (CollectionUtils.isNotEmpty(workOrderIds)) {
            workReminderMapper.deleteCitySubWorkById(workOrderIds);
        }

    }

    /**
     * 市公司下发给支部工单
     * @param mainWork 工单信息
     * @param partyOrgs 组织结构列表
     */
    private void processPartyBranchMainWork(final TaskReminderMainWork mainWork, final List<PartyOrg> partyOrgs) {
        // 更新市公司工单状态
        mainWork.setWorkStatus(ASSIGN_DO);
        workReminderMapper.updateCityMainWork(mainWork);

        final List<PartyOrg> partyOrgList = partyOrgs.stream()
                .filter(partyOrg -> StringUtils.isNotBlank(partyOrg.getCompanyName())
                        && StringUtils.equals(partyOrg.getCompanyName(), mainWork.getCompanyName())
                        && StringUtils.isNotBlank(partyOrg.getOrgShortName()))
                .distinct()
                .collect(Collectors.toList());

        // 旧的支部任务信息
        final List<TaskReminderMainWork> oldMainWorks = workReminderMapper.getBranchMainWorkByIdAndParentWorkId(mainWork);

        // 旧的支部任务信息如果不为空，更新支部任务信息，否则新增支部任务信息
        if (CollectionUtils.isNotEmpty(oldMainWorks)) {
            updateOldBranchMainWork(mainWork, oldMainWorks);
            return;
        }

        createNewBranchMainWork(mainWork, partyOrgList);

    }

    /**
     * 创建新的支部工单
     * @param mainWork 工单信息
     * @param partyOrgList 组织结构
     */
    private void createNewBranchMainWork(final TaskReminderMainWork mainWork, final List<PartyOrg> partyOrgList) {
        final LocalDateTime nowDate = LocalDateTime.now();
        mainWork.setParentWorkId(mainWork.getWorkOrderId());
        mainWork.setCreateTime(nowDate);
        mainWork.setUpdateTime(nowDate);
        final List<TaskReminderSubWork> citySubWorks = workReminderMapper.getCitySubWorkList(mainWork);
        partyOrgList.forEach(partyOrg -> {
            final String mainWorkId = UUID.randomUUID().toString();
            mainWork.setId(mainWorkId);
            mainWork.setWorkOrderId(mainWorkId);
            mainWork.setOrgUuid(partyOrg.getOrgUUID());
            mainWork.setPartyBranch(partyOrg.getOrgShortName());
            mainWork.setFinishStatus(INCOMPLETE);

            workReminderMapper.insertBranchMainWork(mainWork);

            ListUtils.emptyIfNull(citySubWorks).stream()
                    .peek(subWork -> setSubTask(subWork, mainWorkId))
                    .forEach(workReminderMapper::insertBranchSubWork);
        });

    }

    /**
     * 子工单默认赋值
     * @param subWork 子工单信息
     * @param workOrderId 主工单id
     */
    private void setSubTask(final TaskReminderSubWork subWork, final String workOrderId) {
        final String subWorkId = UUID.randomUUID().toString();
        subWork.setId(subWorkId);
        subWork.setSubWorkId(subWorkId);
        subWork.setCreateTime(LocalDateTime.now());

        if (StringUtils.isNotBlank(workOrderId)) {
            subWork.setMainWorkId(workOrderId);
        }
    }

    /**
     * 插入子公司工单
     * @param mainWork 工单信息
     * @param workOrderId 主工单id
     */
    private void insertCitySubWork(final TaskReminderMainWork mainWork, final String workOrderId) {
        ListUtils.emptyIfNull(mainWork.getTaskReminderSubWorks()).stream()
                .peek(subWork -> setSubTask(subWork, workOrderId))
                .forEach(workReminderMapper::insertCitySubWork);
    }

    /**
     * 邮件发送
     * @param companyName 公司名
     * @param issuedMembers 下发人员列表
     */
    private void sendEmail(final String companyName, final List<IssuedMember> issuedMembers) {
        // 发送邮件
//        final String[] userIds = issuedMembers.stream().map(IssuedMember::getUserId).toArray(String[]::new);

        // 正式环境下，邮件发送测试用数据
        final UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromUriString(talkConfig.getSiteUrl()).
                path("/index/talk.htm");
        final String flowType = StringUtils.isNotBlank(companyName) ? PROVINCE : CITY;
        final String url = urlBuilder.replaceQueryParam("workReminder", flowType).build().toString();
        final String contentTemplate = WORK_APPLY_CONTENT + "<br/>链接地址：<a href='" + url + "'>点击此处</a>";
        notifyService.notifyByEmail(new String[]{"zhenglulu14"}, WORK_APPLY_TITLE, contentTemplate);
    }

    /**
     * 创建任务流程工单
     * @param user 用户信息
     * @param request 请求参数信息
     * @param companyName 公司名称
     * @param taskReminderMainWork 任务信息
     */
    private void createWorkApply(final LoginUserPojo user,
                                 final HttpServletRequest request,
                                 final List<IssuedMember> issuedMembers,
                                 final String companyName,
                                 final TaskReminderMainWork taskReminderMainWork) {
        final List<List<ReceiverNameVo>> receiverNames = new ArrayList<>();
        final List<ReceiverUidVo> receiverUids = new ArrayList<>();

        final List<String> userIds = issuedMembers.stream().map(IssuedMember::getUserId).collect(Collectors.toList());

        final List<PartyUser> partyUsers = partyUserMapper.queryByUserIds(
                StringUtils.isBlank(companyName) ? userIds : ImmutableList.of(user.getUserID()));

        partyUsers.forEach(partyUser -> {
            receiverNames.add(ImmutableList.of(new ReceiverNameVo()
                    .setUid(partyUser.getOaId())
                    .setName(partyUser.getDisplayName())
                    .setOrgShortName(partyUser.getOrgShortName())
                    .setQueryByOrg(false)));

            receiverUids.add(new ReceiverUidVo()
                    .setId(partyUser.getOaId())
                    .setLabel(partyUser.getDisplayName())
                    .setType(RECEIVER_TYPE)
                    .setOrgShortName(partyUser.getOrgShortName()));
        });

        // 抄送人信息列表
        final List<ReceiverUidVo> copySubmitList = getCopySubmitList(companyName, taskReminderMainWork, userIds, issuedMembers, user);

        // 根据公司名称是否为空，判断是省公司下发还是市公司分派
        final String copySubmit = JSON.toJSON(copySubmitList).toString();
        final String receiverUid = JSON.toJSON(receiverUids).toString();
        final String receiverName = JSON.toJSON(receiverNames).toString();

        final WorkApplyInfo info = new WorkApplyInfo();
        info.setTitle(WORK_APPLY_TITLE);
        info.setCreateTime(DateTime.now().toDate());

        // 客户要求多条工作子项只取一条展示,需要使用findFirst()方法
        final Optional<TaskReminderSubWork> subWork = ListUtils.emptyIfNull(taskReminderMainWork.getTaskReminderSubWorks()).stream().findFirst();

        // 客户要求多条工作子项只取一条细化说明展示
        final String detailedDescription = subWork.map(TaskReminderSubWork::getDetailedDescription)
                .orElse(StringUtils.EMPTY);
        // 客户要求多条工作子项只取一条工作子项展示
        final String subWorkDescription = subWork.map(TaskReminderSubWork::getSubWorkDescription)
                .orElse(StringUtils.EMPTY);

        // 设置待办主任务描述
        final String mainTaskName = String.format(MAIN_TASK_NAME,
                taskReminderMainWork.getMatterDescription(),
                taskReminderMainWork.getUserName(),
                detailedDescription,
                subWorkDescription,
                taskReminderMainWork.getWorkType() == 0 ? MUST_DO : OPTIONAL);
        info.setMainTaskName(mainTaskName);
        info.setNotifyAfterReportAll(false);
        info.setOpinion(StringUtils.EMPTY);
        info.setDispatched(false);
        info.setCreatorMobile(user.getMobilePhone());
        info.setCreatorDeptDn(user.getAdminOrgDn());
        info.setCreatorDeptName(user.getAdminOrgName());
        info.setCreatorUid(user.getUserID());
        info.setCreatorName(user.getUserName());
        info.setReceiverUid(receiverUid);
        info.setReceiverName(receiverName);
        info.setCopySubmit(copySubmit);

        final WorkSubTaskInfo workSubTaskInfo = new WorkSubTaskInfo();
        workSubTaskInfo.setId(OplogUtils.getUuid32());
        workSubTaskInfo.setName(WORK_APPLY_TITLE);
        workSubTaskInfo.setDescription(WORK_APPLY_CONTENT);
        workSubTaskInfo.setFinishTime(DateTime.now().toDate());
        workSubTaskInfo.setOrderIndex(0);
        workSubTaskInfo.setNewAdd(true);
        workSubTaskInfo.setReportMergeAttachment(false);
        workSubTaskInfo.setReportCount(0);
        workSubTaskInfo.setAutoMergeAttachment(true);
        workSubTaskInfo.setRemoveHandler(true);
        workSubTaskInfo.setFinishTime(Date.from(taskReminderMainWork.getFinishTime().atZone(ZoneId.systemDefault()).toInstant()));

        info.setSubTasks(ImmutableList.of(workSubTaskInfo));

        // 判断是下发还是分派操作
        final String operatorType = StringUtils.isBlank(companyName) ? SubmitDraftOperatorType.REMINDERS_ISSUED.getName()
                : SubmitDraftOperatorType.REMINDERS_DISPATCH.getName();
        workApplyInfoService.submitDraft(info, TASK_ID, StringUtils.EMPTY, user, request, operatorType);
    }

    /**
     * 根据完成状态获取主工单信息
     * @param cityMainWorkStream 主工单流
     * @param finishStatus 完成状态
     * @return 主工单列表
     */
    private List<TaskReminderMainWork> getMainWorkByFinishStatus(final Stream<TaskReminderMainWork> cityMainWorkStream,
                                                                 final String finishStatus) {
        switch (StringUtils.defaultString(finishStatus)) {
            case INCOMPLETE:
                return cityMainWorkStream.filter(mainWork ->
                                !Objects.equals(mainWork.getMainWorkTotal(), mainWork.getFinishMainWorkCount()))
                        .collect(Collectors.toList());
            case COMPLETE:
                return cityMainWorkStream.filter(mainWork -> !Objects.isNull(mainWork.getMainWorkTotal())
                                && Objects.equals(mainWork.getMainWorkTotal(), mainWork.getFinishMainWorkCount()))
                        .collect(Collectors.toList());
            default:
                return cityMainWorkStream.collect(Collectors.toList());
        }
    }

    /**
     * 获取分派时发送待阅的抄送人员信息
     * @param issuedMember 分派时选中的默认人员或组织信息
     * @return 待阅的抄送人员信息列表
     */
    private List<ReceiverUidVo> getCopySubmit(final IssuedMember issuedMember) {
        // 判断待阅人员选择的类型为组织（org）还是人员（person）
        if (StringUtils.equals(issuedMember.getUserType(), RECEIVER_TYPE)) {
            return ImmutableList.of(new ReceiverUidVo()
                    .setId(issuedMember.getUserId())
                    .setLabel(issuedMember.getUserName())
                    .setType(RECEIVER_TYPE)
                    .setOrgShortName(issuedMember.getOrgShortName()));
        }

        return partyUserMapper.getGanshiByOrgUuid(issuedMember.getUserId())
                .stream()
                .map(partyUser -> new ReceiverUidVo()
                        .setId(partyUser.getOaId())
                        .setLabel(partyUser.getDisplayName())
                        .setType(RECEIVER_TYPE)
                        .setOrgShortName(partyUser.getOrgShortName()))
                .collect(Collectors.toList());

    }

    /**
     * 获取抄送人列表
     * @param companyName 公司名称
     * @param taskReminderMainWork 主工单信息
     * @param userIds 用户id列表
     * @param issuedMembers 下发人员列表
     * @param user 当前登录人信息
     * @return 抄送人列表
     */
    private List<ReceiverUidVo> getCopySubmitList(final String companyName,
                                                  final TaskReminderMainWork taskReminderMainWork,
                                                  final List<String> userIds,
                                                  final List<IssuedMember> issuedMembers,
                                                  final LoginUserPojo user) {
        if (StringUtils.isBlank(companyName)) {
            // 省公司下发 （选择的人员需要创建待办工单，未选择的人员创建待阅工单）
            // 获取子任务信息
            taskReminderMainWork.setTaskReminderSubWorks(workReminderMapper.getProvinceSubWorkList(taskReminderMainWork));
            // 获取市公司人员信息
            final List<PartyUser> partyUserLists = getCityPartyUser();

            // 获取抄送人信息
            return partyUserLists.stream()
                    .filter(partyUser -> !userIds.contains(partyUser.getOaId()))
                    .map(partyUser -> new ReceiverUidVo()
                            .setId(partyUser.getOaId())
                            .setLabel(partyUser.getDisplayName())
                            .setType(RECEIVER_TYPE)
                            .setOrgShortName(partyUser.getOrgShortName()))
                    .collect(Collectors.toList());
        }

        // 市公司分派（操作人创建待办工单,选择的干事人员创建待阅）
        // 获取子任务信息
        taskReminderMainWork.setTaskReminderSubWorks(workReminderMapper.getCitySubWorkList(taskReminderMainWork));
        // 获取抄送人信息
        return issuedMembers.stream()
                .map(this::getCopySubmit)
                .flatMap(Collection::stream)
                .filter(item -> !StringUtils.equals(item.getId(), user.getUserID()))
                .collect(Collectors.toList());

    }

    /**
     * 主工单添加细化说明和工作子项信息
     * @param mainWork 主工单信息
     * @param subWorks 子工单信息
     * @return 主工单信息
     */
    private TaskReminderMainWork setMainWorkDescriptions(final TaskReminderMainWork mainWork, final List<TaskReminderSubWork> subWorks) {

        mainWork.setDetailedDescriptions(subWorks.stream()
                .findFirst() // 客户要求默认取第一条工作子项的细化说明展示，需要使用findFirst()方法
                .map(TaskReminderSubWork::getDetailedDescription)
                .orElse(StringUtils.EMPTY));
        mainWork.setSubWorkDescriptions(subWorks.stream()
                .map(TaskReminderSubWork::getSubWorkDescription)
                .distinct()
                .collect(Collectors.joining(COMMA)));
        return mainWork;
    }

    /**
     * 获取查询会议的日期
     * @return 查询日期
     */
    private LocalDateTime getSearchMeetingDate() {
        //获取当前时间
        final LocalDateTime currentDate = LocalDateTime.now();
        // 如果当前日期月份月份大于三月，则取本年的第一天的日期；否则取当前日期减去八个月的日期
        return currentDate.getMonthValue() > MARCH
                ? LocalDateTime.of(LocalDate.from(currentDate.with(TemporalAdjusters.firstDayOfYear())), LocalTime.MIN)
                : currentDate.minusMonths(EIGHT_MONTH);

    }

    /**
     * excel样式设置
     * @return 样式设置
     */
    private HorizontalCellStyleStrategy getWriteCellStyle(){
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);//细实线
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        //设计内容居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);      //设置内容自动换行
        contentWriteCellStyle.setWrapped(true);
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);  // 设置垂直对齐的样式为居中对齐
        contentWriteCellStyle.setShrinkToFit(true);//设置文本收缩至合适
        //设置头部样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置头部标题居中
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

    }

    /**
     * 省公司列表导出.
     * @param workReminderVo 省公司列表查询条件
     * @param response response
     */
    private void provinceExport(final WorkReminderVo workReminderVo, final HttpServletResponse response) {
        final List<ProvinceReminderMainWorkExcelVo> mainWorks = workReminderMapper.getProvinceMainWorkExportList(workReminderVo).stream()
                .peek(mainWork -> mainWork.setWorkTypeContent(mainWork.getWorkType() == 0 ? MUST_DO : OPTIONAL))
                .collect(Collectors.toList());

        easyExcelWrite(response, ProvinceReminderMainWorkExcelVo.class, PROVINCE_MERGE_COLUMN_INDEX, MERGE_ROW_INDEX, mainWorks, PROVINCE_MERGE_COL);

    }

    /**
     * 市公司列表导出.
     * @param workReminderVo 市公司列表查询条件
     * @param response response
     */
    private void cityExport(final WorkReminderVo workReminderVo, final HttpServletResponse response) {
        final List<CityReminderMainWorkExcelVo> mainWorks = workReminderMapper.getCityMainWorkExportList(workReminderVo).stream()
                .peek(this::dealCityMainWork)
                .collect(Collectors.toList());

        easyExcelWrite(response, CityReminderMainWorkExcelVo.class, CITY_MERGE_COLUMN_INDEX, MERGE_ROW_INDEX, mainWorks, CITY_MERGE_COL);
    }

    /**
     * 处理市公司导出的数据结构
     * @param mainWork 主任务数据信息
     */
    private void dealCityMainWork(final CityReminderMainWorkExcelVo mainWork) {
        mainWork.setWorkTypeContent(mainWork.getWorkType() == 0 ? MUST_DO : OPTIONAL);
        if (StringUtils.equals(mainWork.getWorkStatus(), ASSIGN_DO)) {
            final String finishProgress = String.format("%d/%d",
                    workReminderMapper.getBranchCountByParentWorkIdAndFinishStatus(mainWork.getCompanyName(), mainWork.getWorkOrderId()),
                    workReminderMapper.getBranchMainWorkCountByParentWorkId(mainWork.getCompanyName(), mainWork.getWorkOrderId()));
            mainWork.setFinishProgress(finishProgress);
        }else if (StringUtils.equals(mainWork.getWorkStatus(), ISSUED_DO)) {
            // 如果状态是已下发，则导出内容修改为未接收
            mainWork.setWorkStatus(NO_RECEIVED);
        }
    }
    /**
     * 支部列表导出.
     * @param workReminderVo 支部查询条件
     * @param response response
     */
    private void branchExport(final WorkReminderVo workReminderVo, final HttpServletResponse response) {
        final List<BranchReminderMainWorkExcelVo> mainWorks = workReminderMapper.getBranchMainWorkExportList(workReminderVo).stream()
                .peek(mainWork -> mainWork.setWorkTypeContent(mainWork.getWorkType() == 0 ? MUST_DO : OPTIONAL))
                .collect(Collectors.toList());

        easyExcelWrite(response, BranchReminderMainWorkExcelVo.class, BRANCH_MERGE_COLUMN_INDEX, MERGE_ROW_INDEX, mainWorks, BRANCH_MERGE_COL);

    }

    /**
     * 文件导出方法.
     * @param response response
     * @param tClass class
     * @param mergeColumnIndex 合并列设置
     * @param mergeRowIndex 合并开始行
     * @param mainWorks 导出数据
     * @param lastCol 合并列数
     * @param <T> 泛型
     */
    private <T> void easyExcelWrite(final HttpServletResponse response,
                                    final Class<T> tClass,
                                    final int[] mergeColumnIndex,
                                    final int mergeRowIndex,
                                    final List<T> mainWorks,
                                    final int lastCol) {
        try {
            EasyExcel.write(response.getOutputStream(), tClass)
                    .excelType(ExcelTypeEnum.XLSX)
                    .head(tClass)
                    .registerWriteHandler(new TitleSheetWriteHandler(SHEET_NAME, lastCol)) // 标题及样式，lastCol为标题第0列到底lastCol列的宽度
                    //设置默认样式及写入头信息开始的行数
                    .relativeHeadRowIndex(1)
                    .registerConverter(new LocalDateTimeConverter())
                    .registerWriteHandler(new ExcelFillCellMergeStrategyUtils(mergeRowIndex, mergeColumnIndex))
                    .registerWriteHandler(getWriteCellStyle())
                    .sheet(SHEET_NAME)
                    .doWrite(mainWorks);
        } catch (final IOException e) {
            LOGGER.error("导出失败，mainWorks：{}", mainWorks, e);
            throw new RuntimeException(e);
        }

    }
}
